package com.wjw.java.others.static_;

/**
 * 代码块：
 * 属于类中的成员,是类的一部分,类似与方法,将逻辑语句封装在方法体中,使用{}包裹
 * 不同于方法,代码块没有返回值、没有方法名、没有参数,只有方法体
 * 方法是通过对象名.方法名显示调用;代码块是在类加载是时调用,或创建对象时隐式调用
 * ----------------------------------------------------------------------------
 * 基本语法：
 * 修饰符{
 *
 * }
 * 1.修饰符只能用static或不用
 * 2.static修饰的叫静态代码块;没有static的叫普通代码块
 * 3.逻辑语句可以为任何逻辑语句
 * 4.;可以省略,也可以写上
 * ----------------------------------------------------------------------------
 * 代码块的好处:
 * 1.相当于另外一种形式的构造器,可以做初始化的操作
 * 2.场景:如果多个构造器中都有重复的语句,可以抽取到代码块当中
 * ----------------------------------------------------------------------------
 * 代码块细节：
 * 1.普通代码块{},每创建一个对象的时候,就会执行一次
 *   静态代码块static {},只会在类加载的时候,执行一次
 *
 * 2.类什么时候被加载：
 *   创建对象实例(new的时候)
 *   创建子类对象实例,父类对象也会被加载
 *   使用类的静态成员时(成员变量、成员方法)
 *
 * 3.普通代码块,在创建对象实例时,会被隐式调用,创建一次就会被调用一次
 *   如果使用类的静态成员时(成员变量、成员方法),普通代码块不会被执行
 *
 * 4.在创建一个对象时,在一个类调用顺序是:
 *   首先调用静态代码块和静态属性初始化,注意:他们优先级一样,
 *   如果有多个静态代码块和多个静态变量初始化.则按他们定义的顺序调用
 *
 *   然后调用普通代码块和普通属性初始化,注意:他们优先级一样,
 * 如果有多个普通代码块和多个普通变量初始化.则按他们定义的顺序调用
 *
 *   最后调用构造方法
 *
 * 5.构造器的最前面其实隐含了super()和调用普通代码块
 *
 * 6.如果创建一个子类对象时,它的静态属性、静态代码块、普通属性、普通代码块、构造器执行顺序如下：
 *   1.父类：静态代码块和静态属性初始化,(优先级一样)
 *   2.子类：静态代码块和静态属性初始化,(优先级一样)
 *   3.父类：普通代码块和普通属性初始化,(优先级一样)
 *   4.父类：构造器
 *   5.子类：普通代码块和普通属性初始化,(优先级一样)
 *   6.子类：构造器
 *
 * 7.静态代码块只能调用静态成员(属性、方法),
 *   普通代码块可以调用任意成员(属性、方法)
 * ----------------------------------------------------------------------------
 *
 */
public class StaticCodeBlock {
    public static void main(String[] args) {
        Movie m1 = new Movie("侏罗纪公园");
        Movie m2 = new Movie("反贪风暴",35.9);
        Movie m3 = new Movie("反贪风暴2",35.9,"阿威");

        /**
         * 输出结果如下：
         * 因为首先执行：静态属性和静态代码块(优先级一样),静态属性初始化在静态代码块的上面,所以先执行
         * 然后执行：普通属性和普通代码块(优先级一样),普通属性初始化在普通代码块的上面,所以先执行
         * 最后执行：构造器
         * --------------------------------------------------------------------------------------
         * 1.静态属性number初始化了...
         * 2.静态代码初始化...
         * 100
         * 3.静态属性number初始化了...
         * 4.静态代码初始化...
         * 5.构造器被调用了...
         * 200
         */
        System.out.println(Detail.staticNumber);
        Detail d = new Detail();
        System.out.println(d.memberNumber);
    }
}

//为什么使用静态代码块
class Movie{
    private String name;
    private double price;
    private String director;
    public static int num = 9999;
    //1.普通代码块,每创建一个对象就会执行一次
    //将重载的构造器中的相同语句,抽取到代码块中
    {
        System.out.println("1.打开电影屏幕");
        System.out.println("2.电影广告");
        System.out.println("3.电影播放中...");
    }
    //2.静态代码块,只会执行一次(类加载的时候执行)
    static {
        System.out.println("静态代码块中的内容");
    }
    //getter、setter...
    public String getName() {
        return this.name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public double getPrice() {
        return this.price;
    }
    public void setPrice(double price) {
        this.price = price;
    }
    public String getDirector() {
        return this.director;
    }
    public void setDirector(String director) {
        this.director = director;
    }
    public Movie() {
    }
    public Movie(String name) {
//        System.out.println("1.打开电影屏幕");
//        System.out.println("2.电影广告");
//        System.out.println("3.电影播放中...");
        this.name = name;
    }
    public Movie(String name, double price) {
//        System.out.println("1.打开电影屏幕");
//        System.out.println("2.电影广告");
//        System.out.println("3.电影播放中...");
        this.name = name;
        this.price = price;
    }
    public Movie(String name, double price, String director) {
//        System.out.println("1.打开电影屏幕");
//        System.out.println("2.电影广告");
//        System.out.println("3.电影播放中...");
        this.name = name;
        this.price = price;
        this.director = director;
    }
}

//在创建一个对象时,在一个类调用顺序是：一、二、三
class Detail{
    //三、构造方法
    public Detail() {
        System.out.println("5.构造器被调用了...");
    }
    public Detail(int memberNumber) {
        System.out.println("5.构造器被调用了...");
        this.memberNumber = memberNumber;
    }

    //二、普通属性、普通代码块
    //普通属性初始化
    public int memberNumber = getMemberNumber();
    //普通代码初始化
    {
        System.out.println("4.静态代码初始化...");
    }
    private int getMemberNumber() {
        System.out.println("3.静态属性number初始化了...");
        return 200;
    }

    //一、静态属性、静态代码块
    //静态属性初始化
    public static int staticNumber = getStaticNumber();
    //静态代码初始化
    static {
        System.out.println("2.静态代码初始化...");
    }
    private static int getStaticNumber() {
        System.out.println("1.静态属性number初始化了...");
        return 100;
    }

}